Program-wide operational metrics.
Reads counters that live directly on the bound program object —
specifically {phase}_cumulated_invocations and
{phase}_cumulated_invocation_elapsed_s, which
Module._maybe_reset_call_context bumps whenever the program is the
entry module of a top-level call. That gives true wall-clock elapsed
and invocation counts at the program boundary, not a sum of nested
LM/EM per-call times.
For cost, which is paid by individual providers and tracked on each
LanguageModel / EmbeddingModel, the base class also collects the LM
and EM trees reachable from the program (including .fallback chains)
so subclasses can sum across them.
ProgramAvgCostPerInvocation
Bases: ProgramOperationalMetric
Average provider cost per program invocation.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export("synalinks.metrics.ProgramAvgCostPerInvocation")
class ProgramAvgCostPerInvocation(ProgramOperationalMetric):
"""Average provider cost per program invocation."""
def __init__(self, name="program_avg_cost_per_invocation"):
super().__init__(name=name)
def result(self):
calls = self._delta_program("invocations")
if calls <= 0:
return 0.0
return self._delta_model_cost() / calls
|
ProgramCalls
Bases: ProgramOperationalMetric
Number of top-level program invocations during this run.
One increment per call to program(...), regardless of how many LM
or EM calls the program makes internally.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export("synalinks.metrics.ProgramCalls")
class ProgramCalls(ProgramOperationalMetric):
"""Number of top-level program invocations during this run.
One increment per call to `program(...)`, regardless of how many LM
or EM calls the program makes internally.
"""
def __init__(self, name="program_calls"):
super().__init__(name=name)
def result(self):
return int(self._delta_program("invocations"))
|
ProgramCallsPerSecond
Bases: ProgramOperationalMetric
Throughput: program invocations per wall-clock second.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export("synalinks.metrics.ProgramCallsPerSecond")
class ProgramCallsPerSecond(ProgramOperationalMetric):
"""Throughput: program invocations per wall-clock second."""
def __init__(self, name="program_calls_per_second"):
super().__init__(name=name)
def result(self):
elapsed = self._delta_program("invocation_elapsed_s")
if elapsed <= 0.0:
return 0.0
return self._delta_program("invocations") / elapsed
|
ProgramCost
Bases: ProgramOperationalMetric
Total provider cost (USD, as reported by litellm) across every LM
and EM reached from the program for this run. The program object
itself doesn't pay providers — cost is summed from its bound models.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export("synalinks.metrics.ProgramCost")
class ProgramCost(ProgramOperationalMetric):
"""Total provider cost (USD, as reported by litellm) across every LM
and EM reached from the program for this run. The program object
itself doesn't pay providers — cost is summed from its bound models.
"""
def __init__(self, name="program_cost"):
super().__init__(name=name)
def result(self):
return float(self._delta_model_cost())
|
ProgramElapsedTime
Bases: ProgramOperationalMetric
End-to-end wall-clock seconds spent inside program(...) during
this run. Sums per-invocation wall-clock; does not double-count
nested LM/EM calls.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export("synalinks.metrics.ProgramElapsedTime")
class ProgramElapsedTime(ProgramOperationalMetric):
"""End-to-end wall-clock seconds spent inside `program(...)` during
this run. Sums per-invocation wall-clock; does not double-count
nested LM/EM calls.
"""
def __init__(self, name="program_elapsed_time"):
super().__init__(name=name)
def result(self):
return float(self._delta_program("invocation_elapsed_s"))
|
ProgramOperationalMetric
Bases: Metric
Base class for program-wide runtime-counter metrics.
Subclasses set _phase to one of "inference", "reward", or
"optimizer" to read the corresponding counter set. Counters are
populated based on the synalinks_op_scope global flag set by the
trainer.
Source code in synalinks/src/metrics/program_metrics.py
| @synalinks_export(
[
"synalinks.metrics.ProgramOperationalMetric",
"synalinks.ProgramOperationalMetric",
]
)
class ProgramOperationalMetric(Metric):
"""Base class for program-wide runtime-counter metrics.
Subclasses set `_phase` to one of ``"inference"``, ``"reward"``, or
``"optimizer"`` to read the corresponding counter set. Counters are
populated based on the ``synalinks_op_scope`` global flag set by the
trainer.
"""
_phase = "inference"
direction = "down"
def __init__(self, name=None):
super().__init__(name=name)
self._program = None
self._language_models = []
self._embedding_models = []
self._program_baselines = {suffix: 0 for suffix in _PROGRAM_SUFFIXES}
self._model_cost_baseline = 0.0
@property
def program(self):
return self._program
@property
def language_models(self):
return list(self._language_models)
@property
def embedding_models(self):
return list(self._embedding_models)
def bind_program(self, program):
self._program = program
self._language_models = _collect_language_models(program)
self._embedding_models = _collect_embedding_models(program)
self._snapshot()
def _attr(self, suffix):
return f"{self._phase}_cumulated_{suffix}"
def _read_program(self, suffix):
if self._program is None:
return 0
return getattr(self._program, self._attr(suffix), 0)
def _read_model_cost(self):
attr = self._attr("cost")
lm_cost = sum(getattr(lm, attr, 0) for lm in self._language_models)
em_cost = sum(getattr(em, attr, 0) for em in self._embedding_models)
return lm_cost + em_cost
def _snapshot(self):
for suffix in _PROGRAM_SUFFIXES:
self._program_baselines[suffix] = self._read_program(suffix)
self._model_cost_baseline = self._read_model_cost()
def _delta_program(self, suffix):
return self._read_program(suffix) - self._program_baselines.get(suffix, 0)
def _delta_model_cost(self):
return self._read_model_cost() - self._model_cost_baseline
def reset_state(self):
self._snapshot()
async def update_state(self, *args, **kwargs):
return
def result(self):
raise NotImplementedError
def get_config(self):
return {"name": self.name}
|